﻿
// ©Copyright 2012 by James Plotts.  All rights reserved under the Eclipse Public License v 1.0.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using EternalCodeworks.EighthDwarf.Engine;

namespace EighthDwarf
{
    public partial class Game1 : Microsoft.Xna.Framework.Game
    {

        enum eDir
        {
            North = 0,
            East = 1,
            South = 2,
            West = 3,
            Unspecified = -1
        };

        //private Vector3[, ,] modelPosition = new Vector3[MapSize, MapSize, MapSize];
        //System.Collections.Generic.List<MapLocation> VisibleLocations;


        Matrix viewmatrix;
        Matrix projmatrix;

        Boolean MapInitialized = false;
        MouseState oldmousestate; 
        Int32 scrollvalue = 0;
        bool BoxPicked; 
        //LocalMap.MapLocation lastSelected ; 
        private eDir DwarfDir = eDir.North;
        Boolean GamePaused = true;

        //private Int32 modelRotation   = 0;
        //private Matrix modelMatrixRotation   = Matrix.CreateRotationY(MathHelper.ToRadians(0));
        //private Int32 CameraYLookatLevel ; 
        //private Int32 CameraY = 0; 
        //private Matrix CurrentCameraTransform ; 
        Matrix DwarfTurnedWest   = Matrix.CreateRotationY(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(new Vector3(308, 0, 0));
        Matrix DwarfTurnedNorth   = Matrix.CreateTranslation(Vector3.Zero);
        Matrix DwarfTurnedEast   = Matrix.CreateRotationY(MathHelper.ToRadians(270)) * Matrix.CreateTranslation(new Vector3(0, 0, -308));
        Matrix DwarfTurnedSouth   = Matrix.CreateRotationY(MathHelper.ToRadians(180)) * Matrix.CreateTranslation(new Vector3(308, 0, -308));
        static Boolean runonce;
        //private Vector3 cameraPosition ;
        //private Vector3 cameraLookAt   = new Vector3(0, CameraYLookatLevel, 0);
        

        //private long aspectRatio ; 
        //private Single CameraAngle = 0;
        private Boolean runonce2;


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw( Microsoft.Xna.Framework.GameTime gameTime )
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            
            CurrentCameraTransform = Matrix.CreateRotationY(MathHelper.ToRadians(CameraAngle));
            CurrentCameraTransform = CurrentCameraTransform * Matrix.CreateRotationX(MathHelper.ToRadians(20f));

            if ( MapInitialized == true)
            {
                spriteBatch.Begin();
                if (runonce2 == false)
                {
                    String tp = "";
                    if (GamePaused == true) { tp = " (Paused)"; }
                    this.Window.Title = "8th Dwarf Map Initialized" + tp;
                    runonce2 = true;
                }
                viewmatrix = Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up) * CurrentCameraTransform ;
                projmatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), aspectRatio, 1,  farPlaneDistance);
                Int32 drawcount = 0;
                BoundingFrustum fustum = new BoundingFrustum(viewmatrix * projmatrix);
                Boolean foundLocation;
                Int32 MaxElevation = 0;
                Matrix worldtrans = Matrix.CreateTranslation(new Vector3(0, 0, 0)) * CurrentCameraTransform;
                GraphicsDevice.BlendState = BlendState.Opaque;
                GraphicsDevice.DepthStencilState = DepthStencilState.Default; 
                for (Int32 i = 0; i < Engine.LocalMap.Width; i++) 
                {
                    Int32 im = i * LocOffset;
                    for (Int32 j = 0; j < Engine.LocalMap.Length; j++)
                    {
                        Int32 jm = j * LocOffset;
                        foundLocation = false;
                        for (Int32 k = Engine.LocalMap.Height - 1; (k > -1) && (foundLocation == false); k--)
                        {

                            switch (Engine.LocalMap.LocationType(i, j, k))
                            {
                                case LocalMap.eLocationType.SolidGround :
                                    
                                        //worldtrans = ml.Translation  * CurrentCameraTransform;
                                        //if (fustum.Contains(ml.BoundingBox) == ContainmentType.Contains)
                                        //{
                                    Int32 km = k * LocOffset;

                                    

                                    //myModel.Draw(Matrix.CreateTranslation(new Vector3(im, km, jm)), viewmatrix, projmatrix);
                                        //if (ml.Selected == true)
                                        //{
                                        //    SelectionBox.Draw(worldtrans, viewmatrix, projmatrix);
                                        //}
                                        //else
                                        //{
                                        //    if (ml.Picked == true)
                                        //    {
                                        //        HighlightBox.Draw(worldtrans, viewmatrix, projmatrix);
                                        //    }
                                        //}
                                        //if (ml.BoundingBoxSet == false)
                                        //{
                                        //    ml.BoundingBox = CalculateBoundingBox(myModel, worldtrans);
                                        //    ml.BoundingBoxSet = true;
                                        //}
                                        drawcount++;
                                        //}
                                        if (MaxElevation < km) MaxElevation = km;
                                        foundLocation = true;
                                        break;
                                default:
                                        break;

                            }
                        }
                    }
                }
                //String ts = "";
                //if (GamePaused == true) { ts = " (Paused)"; }
                //this.Window.Title = "Elevation: " + CameraY.ToString() + ", CameraAngle: " + CameraAngle.ToString() + ", MaxElevation: " + MaxElevation.ToString(); 
                //this.Window.Title = "8th Dwarf Map Initialized " + drawcount.ToString() + " items drawn (Paused)";
                DrawText();
                DrawMouse();
                spriteBatch.End();
            }
            
            if (runonce != true) 
            {
                runonce = true;
                //CameraAngle = CameraAngle + 135;
            }
            base.Draw(gameTime);
        }

        private void DrawMouse()
        {
            spriteBatch.Draw( MousePointer, MouseDestination, MouseOrigin, Color.White);
        }

        private void DrawText()
        {
            spriteBatch.DrawString(font, "CameraAngle: " + CameraAngle.ToString(), new Vector2(0, 0), Color.White);
            spriteBatch.DrawString(font, "CameraX: " + cameraPosition.X.ToString(), new Vector2(0, 12), Color.White);
            spriteBatch.DrawString(font, "CameraZ: " + cameraPosition.Y.ToString(), new Vector2(0, 24), Color.White);
            spriteBatch.DrawString(font, "CameraZ: " + cameraPosition.Z.ToString(), new Vector2(0, 36), Color.White);
            

        }

        private void DrawSkybox()
        {
            SamplerState ss = new SamplerState();
            ss.AddressU = TextureAddressMode.Clamp;
            ss.AddressV = TextureAddressMode.Clamp;
            this.GraphicsDevice.SamplerStates[0] = ss;

            DepthStencilState dss = new DepthStencilState();
            dss.DepthBufferEnable = false;
            this.GraphicsDevice.DepthStencilState = dss;

            Matrix[] skyboxTransforms = new Matrix[skyboxModel.Bones.Count];
            skyboxModel.CopyAbsoluteBoneTransformsTo(skyboxTransforms);
            int i = 0;
            foreach (ModelMesh mesh in skyboxModel.Meshes)
            {
                foreach (Effect currentEffect in mesh.Effects)
                {
                    Matrix worldMatrix = skyboxTransforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(cameraPosition);
                    currentEffect.CurrentTechnique = currentEffect.Techniques[0];
                    //currentEffect.Parameters["xWorld"].SetValue(worldMatrix);
                    currentEffect.Parameters["View"].SetValue(viewmatrix);
                    currentEffect.Parameters["Projection"].SetValue(projmatrix);
                    currentEffect.Parameters["Texture"].SetValue(skyboxTextures[i++]);
                }
                mesh.Draw();
            }

            dss = new DepthStencilState();
            dss.DepthBufferEnable = true;
            this.GraphicsDevice.DepthStencilState = dss;
        }
    }
}

/*protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            DrawModel(model, world, view, projection);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }*/

//private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
//{
//    foreach (ModelMesh mesh in model.Meshes)
//    {
//        foreach (BasicEffect effect in mesh.Effects)
//        {
//            effect.World = world;
//            effect.View = view;
//            effect.Projection = projection;
//        }

//        mesh.Draw();
//    }
//}










        


        

